#ifndef CLOGIN_H_INCLUDED
#define CLOGIN_H_INCLUDED

#include "GlobalConfig.h"

#include <vector>
#include <map>
#include <stdexcept>

#include "CHttpReq.h"
#include "CQuery.h"
//#define CONNECTION_ERROR "o(︶︿︶)o  连接失败"


/*******************
System Table Column Fields:

user_id ,
access_token ,
access_secret ,
followers_count ,
friends_count

*******************/

class TiXmlDocument;
class TiXmlNode;
class Oauth;
class wxCriticalSection;

class CLogin
{
    typedef TiXmlDocument DOM;
    typedef TiXmlNode Node;
    friend class UnitTest_Login;

    public:
        enum OauthErrorType
        {
            INVALID_ERROR_TYPE = 0,
            UNKNOWN_ERROR,
            HTTP_DISCONNECTED,
            REQUEST_TOKEN_UNAUTHORIZED,
            REQUEST_TOKEN_UNRECOGNIZED_DATA,
            ACCESS_TOKEN_UNAUTHORIZED,
            ACCESS_TOKEN_UNRECOGNIZED_DATA,
            ACCOUNT_UNAUTHORIZED,
            ACCOUNT_UNRECOGNIZED_DATA,

            NO_ERROR = 99,
        };

        enum OauthTokenType
        {
           REQUEST_TOKEN,
           ACCESS_TOKEN,
        };

    private :
        enum LoginStateType
        {
            OAUTH_STATE_INVALID = 0,
            OAUTH_ERROR,

            OAUTH_REQEUST_TOKEN_PREPARE,
            OAUTH_REQEUST_TOKEN_HTTPREQ,
            OAUTH_REQEUST_TOKEN_RESPONSE,
            OAUTH_REQEUST_TOKEN_DONE,

            OAUTH_ACCESS_TOKEN_PREPARE,
            OAUTH_ACCESS_TOKEN_HTTPREQ,
            OAUTH_ACCESS_TOKEN_RESPONSE,
            OAUTH_ACCESS_TOKEN_DONE,
        };

        CHttpReq mHttpReq;
        Oauth& mOauth;
        CQuery sysParamDB;
        std::map<wxString, wxString> mHttpReceivedData;
        LoginStateType mLoginState;
        LoginStateType mLoginStatePrevious;

        wxCriticalSection* mpStateMachineCS;
        wxCriticalSection* mpParserCS;
        wxCriticalSection* mpChangeStateCS;
        wxCriticalSection* mpXMLParserCS;

        void Init();
        bool prepareForReqToken();
        bool prepareForAccessToken(const wxString& _PIN);
        bool parseXMLUserInfo(const wxString& xmlRawStr);
        bool Finalize();
        void Destroy();

        inline bool parseReceivedData(wxString rawStr);
        inline void changeStateTo(LoginStateType _nextState);

    public :
        CLogin();
        virtual ~CLogin();

        OauthErrorType mLoginError;

        bool getToken(OauthTokenType tokenType, const wxString& PIN="");
        bool getUserInfo(const wxString& accountVerifyAPI);
        OauthErrorType getErrorCode() const {return mLoginError;}
        bool isLogin();
        void logout();
};

#endif // CLOGIN_H_INCLUDED
